package com.suray.wcs.service.thread;


import com.google.common.base.Joiner;
import com.suray.basic.wcs.node.WCSNodeModule;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.enums.NodeStatus;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.path.exception.CreatePathFailedException;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.utils.Action;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.exception.*;
import com.suray.rgv.util.ErrorInfo;
import com.suray.type.ErrorLevel;
import com.suray.wcs.res.enums.RgvStatus;
import com.suray.wcs.res.enums.RgvType;
import com.suray.wcs.service.core.path.api.DeadlockHandle;
import com.suray.wcs.service.core.path.api.impl.DeadLockHandleImpl;
import com.suray.wcs.service.core.util.CommonUtil;
import com.suray.wcs.service.core.util.LockNodeManager;
import com.suray.wcs.service.enums.*;
import com.suray.wcs.service.execption.*;
import com.suray.wcs.service.init.SystemInit;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.pojo.Rgv60;
import com.suray.wcs.service.pojo.rgv.action.util.RgvTaskMode;
import com.suray.wcs.service.rescontact.ActionHandle;
import com.suray.wcs.service.rescontact.ToRes;
import com.suray.wcs.service.system.entity.NodeDB;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.entity.TaskDetailDB;
import com.suray.wcs.service.system.service.INodeDBService;
import com.suray.wcs.service.system.service.IWareHouseDBService;
import com.suray.wcs.service.system.service.impl.*;
import com.suray.wcs.service.util.WcsUtil;
import com.suray.wcs.service.wmsconnect.TaskStatusRtn;
import com.suray.wcs.service.wmsconnect.ToWms;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class RgvExecuteThread extends Thread {
    RgvTaskHandle taskHandle = SpringContextHolder.getBean(RgvTaskHandle.class);
    private final TaskDBServiceImpl taskService = SpringContextHolder.getBean(TaskDBServiceImpl.class);
    private Logger log = LoggerFactory.getLogger(this.getClass());
    private final ExceptionLogServiceImpl exceptionLogService = SpringContextHolder.getBean(ExceptionLogServiceImpl.class);
    private final INodeDBService nodedbService = SpringContextHolder.getBean(INodeDBService.class);
    private final CodeDBServiceImpl codeDBService = SpringContextHolder.getBean(CodeDBServiceImpl.class);
    private DeadlockHandle deadlockHandle = SpringContextHolder.getBean(DeadLockHandleImpl.class);
    private ToWms toWms = SpringContextHolder.getBean(ToWms.class);
    private IWareHouseDBService wareHouseDBService = SpringContextHolder.getBean(IWareHouseDBService.class);
    private TaskDetailServiceImpl taskDetailService = SpringContextHolder.getBean(TaskDetailServiceImpl.class);
    private RgvDBServiceImpl rgvDBService = SpringContextHolder.getBean(RgvDBServiceImpl.class);

    private Rgv rgv;

    public Rgv getRgv() {
        return rgv;
    }

    public void setRgv(Rgv rgv) {
        this.rgv = rgv;
    }

    private String name;

    public RgvExecuteThread(String name, Rgv rgv) {
        super(name + "执行任务");
        this.name = name;
        this.rgv = rgv;
    }

    @Override
    public void run() {
        log.info(name + "小车执行任务的线程启动");
        try {
            monitorsExecute();
        } catch (InterruptedException e) {
            WcsUtil.exceptionLog(e, this.getClass());
        }
        super.run();
    }

    private void monitorsExecute() throws InterruptedException {
        Random random = new Random(rgv.getRgvDB().getRgvId());
        int i = 0;
        while (true) {
            try {
                if (rgv.getCurLocation() != null && (RgvStatus.READY.equals(rgv.getRgvStatus()) || RgvStatus.CHARGING.equals(rgv.getRgvStatus())) && isCanExecuteTaskBattery(rgv)) {
                    //寻找当前车辆可以做的第一个任务
                    TaskDB taskDB = taskService.findFirstCanExecuteTaskForPreAssignAdjustOrAssigned(rgv.getRgvDB().getRgvNo());
                    if (taskDB != null && ((TaskType.OUT.equals(taskDB.getTaskType()) && rgv.getRgvDB().getPriorityMode().equals(TaskType.IN.getValue()))
                            || (TaskType.IN.equals(taskDB.getTaskType()) && rgv.getRgvDB().getPriorityMode().equals(TaskType.OUT.getValue())))
                            && !TaskRgvProgress.RGV_TO_END.equals(taskDB.getRgvProgress())) {
                        List<TaskDB> tasks = taskService.findPreProcessingTasksByRgvNoAndTaskType(rgv.getRgvDB().getRgvNo(), TaskType.parseTaskType(rgv.getRgvDB().getPriorityMode()));
                        if (CollectionUtils.isNotEmpty(tasks)) {
                            log.info("{}有预分配的入库任务，{}重新预分车", rgv.getRgvName(), taskDB.getTaskId());
                            taskService.updateTaskProcessingRgvNoAndPreProcessingRgvNo(taskDB, null, TaskRgvProgress.PREASSIGN, false);
                            continue;
                        }
                    }
                    if (taskDB != null && taskDB.getTaskStatus() != TaskStatus.ERROR && isLowElectricAndWmsTaskOrSufTask(rgv, taskDB, taskService)) {//当有任务，并且当前车辆无故障则进行处理
                        try {
                            TaskDetailDB rgvTaskDetail = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.RGV_TASK, null, taskDB.getStartNodeStr(), taskDB.getEndNodeStr(), PrecessStatus.CONDUCT,
                                    rgv.getRgvDB().getRgvNo().toString(), Joiner.on("-").join(Arrays.asList(PrecessOperation.INTERRUPT.getValue(), PrecessOperation.RECOVER.getValue())));
                            if (rgv.getRgvStatus() == RgvStatus.CHARGING) {
                                ActionHandle.actionHandle(taskDB, rgvTaskDetail, rgv, null, null, Action.ENDCHARGE);
                            }

                            if (rgv.getRgvTaskMode() == RgvTaskMode.NORMAL) {
                                if (rgv.getRgvDB().getCodeCalibration() != null && !rgv.getRgvDB().getCodeCalibration()) {
                                    ToRes.getInstance(rgv).swicthCalibitionMode(null, true);
                                    rgv.getRgvDB().setCodeCalibration(true);
                                    rgvDBService.updateById(rgv.getRgvDB());
                                }
                            }

                            rgv.setCurTask(taskDB);
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                TaskDetailDB startTaskDetail = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.TO_WMS_START, rgvTaskDetail.getUuid(), null, null,
                                        PrecessStatus.CONDUCT, null, null);
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.START));
                                taskDetailService.updateTaskDetailCompleteTime(startTaskDetail);
                            }
                            initRgv(rgv);
                            if (i == 0 && rgv.getRgvStatus() == RgvStatus.NODE_STANDBY) {
                                initRgvRes(0);
                                i = 1;
                            }
                            if (taskDB.getTaskType().checkIfRgvSonTask())
                                taskHandle.rgvSonNewTaskHandle(taskDB);
                            else {
                                taskHandle.handle(taskDB, rgvTaskDetail);
                            }
                            TaskDB nextTaskDB = taskService.findFirstCanExecuteTask(rgv.getRgvDB().getRgvNo());
                            if (nextTaskDB != null && nextTaskDB.getTaskStatus() == TaskStatus.AVOID) {
                                int result = random.nextInt(10) + 1;
                                Thread.sleep(result * 1000);
                                log.info("改变避让任务为等待,任务Id：" + nextTaskDB.getTaskId());
                                taskService.updateTaskStatus(nextTaskDB, TaskStatus.WAIT);
                            }
                            taskDetailService.updateTaskDetailCompleteTime(rgvTaskDetail);
                        } catch (CreatePathFailedException e) {
                            log.error("{}路径规划失败,已取消当前任务!{}", taskDB.getTaskId(), e.getMessage(), e);
                            cleanTaskNo();
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.SYSTEMEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvName(), rgv.getRgvStatus().getRgvStatus(), null, null);
                            //路径规划失败按照任务失败处理
                            updateTask(taskDB, "路径规划失败了！", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            rgv.setErrorMessage("路径规划失败了！" + e.getMessage());
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "路径规划失败了"));
                            }
                            buildDetail(taskDB, DetailProcess.CREATE_PATH_FAIL, null, "路径规划失败了！" + e.getMessage());
                            initRgvRes(0);
                        } catch (OrderExecuteException e) {//命令行驶异常
                            log.error("RES命令执行失败!{}", e.getMessage(), e);
                            cleanTaskNo();
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.RESEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvName(), rgv.getRgvStatus().getRgvStatus(), e.getCode(), null);
                            updateTask(taskDB, "RES命令执行失败!", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            rgv.setErrorMessage(e.getMessage());
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "RES命令执行失败"));
                            }
                            buildDetail(taskDB, DetailProcess.RES_EXCUTE_ORDER_FAIL, null, "RES命令执行失败!" + e.getMessage());
                            initRgvRes(0);
                        } catch (RgvReTaskException e) {
                            log.error("任务重新执行:" + e.getMessage());
                            rgvReTaskAction(rgv, taskDB, e);
                        } catch (IOException e) {
                            log.error("网络通讯异常！{}s", e.getMessage(), e);
                            cleanTaskNo();
                            updateErrorPriorityCode(taskDB);
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            rgv.setErrorMessage("网络通讯异常！");
                            initRgvRes(0);
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "网络通讯异常"));
                            }
                        } catch (InterruptTaskThenAvoidException e) { //车辆运行过程中遇到排斥或死锁
                            log.error("中断!{}", e.getMessage(), e);
                            rgv.setCurResTaskNo(null);
                            updateTaskStatusForInterrupt(taskDB);
                            initRgvRes(0);
                            TaskDB task = taskService.findFirstCanExecuteTaskForPreAssignAdjustOrAssigned(rgv.getRgvDB().getRgvNo());
                            buildDetail(taskDB, DetailProcess.AVOID_INSERT, task.getEndNodeStr(), task.getTaskType().getDescription());
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "中断!开始避让"));
                            }
                        } catch (InterruptTaskException e) {
                            initRgvRes(taskDB.getTaskId());
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            updateTask(taskDB, "手动中断!", e.getMessage());
                            cleanTaskNo();
                            rgv.setErrorMessage(e.getMessage());
                            rgv.setRejectStatusInfo("小车当前任务：" + taskDB.getTaskId() + "被强制取消");
                            log.error("系统运行异常：取消正在执行任务{}", e.getMessage(), e);
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "任务被强制取消"));
                            }
                            buildDetail(taskDB, DetailProcess.HAND_INTERRUPT, null, e.getMessage());
                        } catch (OutAdjustException e) {
                            initRgvRes(taskDB.getTaskId());
                            cleanTaskNo();
                            TaskDetailDB taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.RGV_TO_START, null, null, null, PrecessStatus.CONDUCT, rgv.toString(), null);
                            TaskDetailDB buildTask = taskDetailService.buildTask(taskDB.getTaskId(), DetailProcess.ADJUST_TASK, taskDetailDB.getUuid(), null, null, PrecessStatus.CONDUCT,
                                    null, null);
                            taskDetailService.updateTaskDetailCompleteTime(buildTask);
                        } catch (PalletDownException e) {
                            log.error("托盘下降异常!{}", e.getMessage(), e);
                            cleanTaskNo();
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.SYSTEMEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvName(), rgv.getRgvStatus().getRgvStatus(), null, null);
                            updateTask(taskDB, "托盘下降异常!", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            rgv.setErrorMessage(e.getMessage());
                            initRgvRes(0);
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "托盘下降异常"));
                            }
                            buildDetail(taskDB, DetailProcess.PALLET_DOWN_EXCEPTION, null, taskDB.getEndNodeStr());
                        } catch (Rgv60TaskException e) {
                            log.error("6代车任务执行异常{}", e.getMessage(), e);
                            cleanTaskNo();
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.RESEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvDB().getRgvNo() + "号车",
                                    rgv.getRgvStatus().getRgvStatus(), null, null);
                            if (rgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                                ((Rgv60) rgv).rgvError(null);
                            } else {
                                rgv.setRgvStatus(RgvStatus.ERROR);
                            }
                            updateTask(taskDB, "6代车任务执行异常", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);

                            if (e.getErrorCode() != null) {
                                //根据异常码查找数据库
                                rgv.setErrorMessage(codeDBService.getCodeDescByType(CodeType.RGV_SON_TYPE.getState(), e.getErrorCode()));
                            } else {
                                rgv.setErrorMessage(e.getMessage());
                            }
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(),
                                        WmsTaskStatus.INTERRUPT, "6代车任务执行异常"));
                            }
                            buildDetail(taskDB, DetailProcess.SYSTEM_EXCEPTION, null, e.getMessage());
                            initRgvRes(0);
                        } catch (Rgv60CommFailException e) {
                            log.error("6代车命令执行失败{}", e.getMessage(), e);
                            cleanTaskNo();
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.RESEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvDB().getRgvNo() + "号车",
                                    rgv.getRgvStatus().getRgvStatus(), null, null);
                            if (rgv.checkRgvType(RgvType.RGV_SEER_COMM)) {
                                ((Rgv60) rgv).rgvError(new ErrorInfo(e.getCode(), e.getMsg(), ErrorLevel.ERROR_LEVEL_2));
                            }
                            updateTask(taskDB, "6代车任务执行时通讯异常", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);

                            rgv.setErrorMessage("异常码:" + e.getCode() + ", 异常原因:" + e.getMsg());
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(),
                                        WmsTaskStatus.INTERRUPT, "6代车任务执行异常"));
                            }
                            buildDetail(taskDB, DetailProcess.SYSTEM_EXCEPTION, null, e.getMessage());
                            initRgvRes(0);
                        } catch (Rgv60InterruptException e) {
                            initRgvRes(taskDB.getTaskId());
                            exceptionLogService.addExceptionLog(e, WcsExceptionType.RESEXCEPTION.getVal()
                                    , taskDB.getTaskId(), rgv.getRgvDB().getRgvNo() + "号车",
                                    rgv.getRgvStatus().getRgvStatus(), null, null);
                            updateTask(taskDB, "手动中断！", e.getMessage());
                            cleanTaskNo();
                            rgv.setErrorMessage(e.getMessage());
                            rgv.setRejectStatusInfo("小车当前任务：" + taskDB.getTaskId() + "被强制取消");
                            log.error("系统运行异常：取消正在执行任务{}", e.getMessage(), e);
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "任务被强制取消"));
                            }
                            buildDetail(taskDB, DetailProcess.HAND_INTERRUPT, null, e.getMessage());
                        } catch (Exception e) {
                            log.error("系统运行异常{}", e.getMessage(), e);
                            cleanTaskNo();
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            updateErrorPriorityCode(taskDB);
                            updateTaskErrorStatus(taskDB, "系统运行异常", e.getMessage());
                            rgv.setRgvStatus(RgvStatus.ERROR);
                            rgv.setErrorMessage(StringUtils.substring(e.getMessage(), 0, 100));
                            if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
                                toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT, "系统运行异常"));
                            }
                            buildDetail(taskDB, DetailProcess.SYSTEM_EXCEPTION, null, e.getMessage());
                            initRgvRes(0);
                        }
                    } else {
                        if (taskDB == null) {
                            rgv.setCurTask(null);
                            rgv.setCurResTaskNo(null);
                            rgv.setWaitConnectPointNoGoods(false);
                            rgv.setExecuteNodeList(null);
                            rgv.setWaitExecuteNodeList(null);
                            rgv.setWcsTimeModuleResultBO(null);
                        } else if (taskDB.getTaskStatus() == TaskStatus.ERROR) {
                            rgv.setRejectStatusInfo("小车当前任务：" + taskDB.getTaskId() + "状态错误");
                        } else if (taskDB.getTaskStatus() == TaskStatus.AVOID) {
                            rgv.setRejectStatusInfo("小车当前任务：" + taskDB.getTaskId() + "正在等待避让");
                        } else if (rgv.getCurLocation() == null) {
                            rgv.setRejectStatusInfo("小车没有同步位置");
                        } else if (RgvStatus.NODE_STANDBY.equals(rgv.getRgvStatus())) {
                            rgv.setRejectStatusInfo(String.format("小车当前状态：%s", RgvStatus.NODE_STANDBY.getDescription()));
                            try {
                                initRgvRes(0);
                            } catch (Exception exc) {
                                log.error("小车待命中，初始化失败：{}", exc.getMessage(), exc);
                                rgv.setRgvStatus(RgvStatus.ERROR);
                                rgv.setErrorMessage(String.format("小车待命中，初始化失败：{}", exc.getMessage()));
                            }
                        } else if (!RgvStatus.READY.equals(rgv.getRgvStatus()) || !RgvStatus.CHARGING.equals(rgv.getRgvStatus())) {
                            rgv.setRejectStatusInfo(String.format("小车当前状态：%s", rgv.getRgvStatus() != null ? rgv.getRgvStatus().getDescription() : StringUtils.EMPTY));
                        }
                    }
                }
            } catch (Exception e) {
                log.error(rgv.getRgvName() + "执行任务系统运行异常：", e);
                TimeUnit.SECONDS.sleep(1);
            }
            TimeUnit.SECONDS.sleep(1);
        }
    }

    /**
     * 重新执行任务
     * @param rgv
     * @param taskDB
     * @param e
     */
    private void rgvReTaskAction(Rgv rgv, TaskDB taskDB, RgvReTaskException e) {
        int tick = rgv.getWaitReleaseNode().size() * 4;
        while (!(rgv.getRgvStatus() == RgvStatus.READY || rgv.getRgvStatus() == RgvStatus.NODE_STANDBY)) {
            if (tick == 0) {
                reTaskError(rgv, taskDB, e);
                return ;
            } else {
                tick --;
            }
            WcsFuncUtil.delay(1000);
        }
        ToRes.getInstance(rgv).initialize(taskDB.getTaskId());
        TaskDB task = new TaskDB();
        task.setTaskId(taskDB.getTaskId());
        task.setPriorityCode(CommonUtil.PRIORITY_RE_TASK);
        taskService.updateById(task);
        LoggerUtil.info("小车初始化完成，重新执行任务", this.getClass());
    }

    /**
     * 重新执行任务时错误
     */
    private void reTaskError(Rgv rgv, TaskDB taskDB, RgvReTaskException e) {
        exceptionLogService.addExceptionLog(e, WcsExceptionType.RESEXCEPTION.getVal()
                , taskDB.getTaskId(), rgv.getRgvDB().getRgvNo() + "号车",
                rgv.getRgvStatus().getRgvStatus(), null, null);
        updateTask(taskDB, "重新执行任务时小车状态长时间不就绪且不处于等待执行！", e.getMessage());
        cleanTaskNo();
        rgv.setErrorMessage(e.getMessage());
        log.error("重新执行任务时小车状态长时间不就绪且不处于等待执行", e.getMessage(), e);
        if (StringUtils.isNotBlank(taskDB.getWmsTaskId())) {
            toWms.executionPhase(TaskStatusRtn.buildTaskStatusRtn(taskDB.getWmsTaskId(), WmsTaskStatus.INTERRUPT,
                    "更换出库口失败"));
        }
        buildDetail(taskDB, DetailProcess.SYSTEM_EXCEPTION, null, e.getMessage());
    }

    /**
     * 任务排斥中断的时候更新状态
     *
     * @param taskDB
     */
    private void updateTaskStatusForInterrupt(TaskDB taskDB) {
        if (taskDB != null && taskDB.getPriorityCode() != null &&
                (taskDB.getPriorityCode().intValue() == CommonUtil.PRIORITY_CODE_AVOID || TaskType.MOVE_UNLOADED.equals(taskDB.getTaskType()))) {
            taskService.updateTaskRgvProgress(taskDB, TaskRgvProgress.RGV_COMPLETE);
            taskService.updateTaskStatus(taskDB, TaskStatus.FINISH);
            String value = Plc.PLC_INTERRUPT_CACHE.get(String.valueOf(taskDB.getTaskId()));
            if (!org.springframework.util.StringUtils.isEmpty(value)) {
                Plc.PLC_INTERRUPT_CACHE.remove(String.valueOf(taskDB.getTaskId()));
            }
        } else {
            if (taskDB.getTaskStatus().getProgressNum() < TaskStatus.FINISH.getProgressNum()) {
                updateAvoidPriorityCode(taskDB);
                taskService.updateTaskStatus(taskDB, TaskStatus.AVOID);
            }
        }
    }

    private void updateTask(TaskDB taskDB, String s, String message) {
        updateTaskErrorStatus(taskDB, s, message);
        updateErrorPriorityCode(taskDB);
    }

    /**
     * 更新任务错误状态和原因
     *
     * @param taskDB
     * @param s
     * @param message
     */
    private void updateTaskErrorStatus(TaskDB taskDB, String s, String message) {
        taskService.updateTaskStatus(taskDB, TaskStatus.ERROR);
        taskService.updateTaskTips(taskDB, s + message);
    }

    /**
     * 初始化小车RES
     *
     * @param i2
     */
    private void initRgvRes(int i2) {
        ToRes toRes = ToRes.getInstance(rgv);
        toRes.initialize(i2);
    }

    /**
     * 任务错误后清除一些任务信息
     */
    private void cleanTaskNo() {
        rgv.generalErrorTaskId();
        rgv.setCurTask(null);
        rgv.setCurResTaskNo(null);
        rgv.setWcsTimeModuleResultBO(null);
        WCSNodeModule.cleanWcsNodeModuleMapCacheRouteBy(rgv.getRgvDB().getRgvNo());
    }

    /**
     * 初始化小车，一些对象设置为NULL
     *
     * @param rgv
     */
    private void initRgv(Rgv rgv) {
        rgv.setRejectRgv(null);
        rgv.setWaitRgv(null);
        rgv.setWaitTasks(null);
        rgv.setWaitConnectPointNoGoods(false);
        rgv.setWaitChaOrConRgvList(null);
        rgv.setWaitSingleRoadRgvS(null);
    }

    /**
     * 当前小车缓存位不为空，当前小车不在缓存位上，当前小车状态不是充电中，当前小车托板下降状态，生成去缓存位的任务
     * 无缓存位且小车位置在单开口巷道，则生成去最近的双开口巷道的任务
     */
    private void goToFreeLocation(Rgv rgv) {
        if (rgv.getCurLocation() != null && rgv.getRgvStatus() != RgvStatus.CHARGING && rgv.getRgvDB().getOnline()
                && !rgv.isHasCargo() && wareHouseDBService.getCurWareHouseDB().getFreeLocationFlag()) {
            NodeDB curLocationNodeDB = nodedbService.getNodeDB(rgv.getCurLocation());
            if (curLocationNodeDB != null && ((NodeType.P.equals(curLocationNodeDB.getGridType()) &&
                    (RoadType.S.getValue().equals(curLocationNodeDB.getRoadType()) || StringUtils.isBlank(curLocationNodeDB.getRoadType())))
                    || NodeType.R.equals(curLocationNodeDB.getGridType())
                    || NodeType.CONNECTION.equals(curLocationNodeDB.getGridType())
                    || NodeType.L.equals(curLocationNodeDB.getGridType()))) {
                List<Coord> availableNodeList = nodedbService.findSpecifiedNodesByRoadType(rgv.isHasCargo() ? NodeType.R : NodeType.P, rgv.isHasCargo() ? NodeStatus.N
                        : null, rgv.getCurLocation().getZ(), RoadType.D.getValue());
                availableNodeList.removeAll(LockNodeManager.getLockedNodes());
                Node bestNode = deadlockHandle.getBestAvoidNode(availableNodeList, rgv);
                if (bestNode != null) {
                    buildTask(bestNode, rgv.getRgvDB().getRgvNo());
                }
            }
        } else {
            rgv.setRejectStatusInfo("小车当前没有任务");
        }
    }

    private void buildDetail(TaskDB taskDB, DetailProcess detailProcess, String end, String deviceInfo) {
        TaskDetailDB taskDetailDB;
        if (TaskRgvProgress.RGV_TO_END.equals(taskDB.getRgvProgress())) {
            taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.RGV_TO_END, null, null, null, PrecessStatus.CONDUCT, rgv.toString(), null);
        } else {
            taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.RGV_TO_START, null, null, null, PrecessStatus.CONDUCT, rgv.toString(), null);
        }
        TaskDetailDB detailDB = taskDetailService.buildTask(taskDB.getTaskId(), detailProcess, taskDetailDB.getUuid(), null, end, PrecessStatus.CONDUCT,
                deviceInfo, null);
        taskDetailService.updateTaskDetailCompleteTime(detailDB, PrecessStatus.EXCEPTION);
    }

    /**
     * 创建一个空载任务去避让
     *
     * @param bestNode
     * @param rgvNo
     */
    private void buildTask(Node bestNode, Integer rgvNo) {
        TaskDB task = new TaskDB();
        task.setEndNode(bestNode);
        task.setTaskType(TaskType.MOVE_UNLOADED);
        task.setProcessingRgvNo(rgvNo);
        taskService.insertTask(Collections.singletonList(task));
        log.info("{}状态：{},当前没有要执行的任务生成去节点：{}的空载任务：{}", rgv.getRgvName(), rgv.getRgvStatus(), bestNode, task.getTaskId());
    }

    /**
     * 故障任务设置优先级
     *
     * @param taskDB
     */
    private void updateErrorPriorityCode(TaskDB taskDB) {
        if (taskDB.getPriorityCode() != null && taskDB.getPriorityCode() < CommonUtil.PRIORITY_CODE_ERROR) {
            if (CommonUtil.PRIORITY_CODE_BALANCE.equals(taskDB.getPriorityCode())) {
                taskDB.setPriorityCode(CommonUtil.PRIORITY_CODE_BALANCE);// 均衡任务优先级
            } else {
                taskDB.setPriorityCode(CommonUtil.PRIORITY_CODE_ERROR);// 错误任务优先级
            }
        }
        taskService.updateSortCode(taskDB);
    }

    /**
     * 避让状态任务设置优先级
     *
     * @param taskDB
     */
    private void updateAvoidPriorityCode(TaskDB taskDB) {
        if (taskDB.getPriorityCode() != null && taskDB.getPriorityCode() < CommonUtil.PRIORITY_CODE_AVOID_STATUS) {
            taskDB.setPriorityCode(CommonUtil.PRIORITY_CODE_AVOID_STATUS);// 错误任务优先级
        }
        taskService.updateSortCode(taskDB);
    }

    /**
     * 低电量的情况下也可执行进行中的任务
     * 或者充电任务
     *
     * @param rgv
     * @param taskDB
     * @param taskService
     * @return
     */
    public static boolean isLowElectricAndWmsTaskOrSufTask(Rgv rgv, TaskDB taskDB, TaskDBServiceImpl taskService) {
        TaskDB sufTask = taskService.findSufTaskByPreTaskId(taskDB.getTaskId());

        if (rgv.getElectricStatus() != ElectricStatus.LOW_BATTERY || taskDB.getTaskType().equals(TaskType.CHARGE) || taskDB.getTaskType().equals(TaskType.MOVE_LOADED)) {
            return true;
        } else {
            if (TaskRgvProgress.RGV_TO_START.equals(taskDB.getRgvProgress()) || TaskRgvProgress.RGV_TO_END.equals(taskDB.getRgvProgress())) {
                return true;
            }
            if (sufTask != null && StringUtils.isNotEmpty(sufTask.getWmsTaskId())) {
                return true;
            }
        }

        if (rgv.getRgvError().getBatteryError().getValue() <= ErrorLevel.ERROR_LEVEL_2.getValue()) {
            return false;
        }

        rgv.setStatusDescription("当前电量处于低电量阶段!");
        return false;
    }

    /**
     * 判断当前电量是否可执行任务
     *
     * @return true 可以执行  false 不可执行
     */
    public static boolean isCanExecuteTaskBattery(Rgv rgv) {
        if (rgv.getRgvStatus() == RgvStatus.CHARGING && rgv.getBattery() < rgv.getRgvDB().getAssignBatterySize()
                && rgv.getElectricStatus() != ElectricStatus.ERROR_BATTERY) {
            return false;
        } else if (rgv.getRgvStatus() == RgvStatus.CHARGING && rgv.getBattery() >= rgv.getRgvDB().getAssignBatterySize()
                && rgv.getBattery() < rgv.getRgvDB().getMaxBatterySize()
                && SystemInit.isTimeOut(rgv)) {
            return false;
        } else {
            return true;
        }
    }
}
